package com.aliang.shopping.util;

import com.aliang.shopping.service.OrdersInfoService;
import com.aliang.shopping.service.UserInfoService;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * Redis延迟队列工具类
 */
@Component
@Slf4j
public class RedisDelayUtil {
    private static final String REDIS_DELAY_QUEUE_KEY = "delay_queue";
    private final RedissonClient redissonClient;
    private final RDelayedQueue<Object> delayedQueue;
    private final OrdersInfoService ordersInfoService;
    private final UserInfoService userInfoService;

    public RedisDelayUtil(RedissonClient redissonClient, OrdersInfoService ordersInfoService, UserInfoService userInfoService) {
        this.redissonClient = redissonClient;
        this.ordersInfoService = ordersInfoService;
        this.userInfoService = userInfoService;
        //1 创建队列
        RBlockingQueue<Object> blockingDueue = redissonClient.getBlockingQueue(REDIS_DELAY_QUEUE_KEY);
        //2 把创建队列放到延迟队列里面
        delayedQueue = redissonClient.getDelayedQueue(blockingDueue);
    }

    @PostConstruct
    public void listener() {
        new Thread(() -> {
            while (true) {
                //获取延迟队列里面阻塞队列
                RBlockingQueue<JSONObject> blockingQueue = redissonClient.getBlockingQueue(REDIS_DELAY_QUEUE_KEY);
                //从队列获取消息
                try {
                    JSONObject orderInfo = blockingQueue.take();

                    //取消订单
                    if (orderInfo.containsKey("id")) {
                        Long orderId = orderInfo.getLong("id");
                        Long userId = orderInfo.getLong("userId");
                        //调用方法取消订单
                        this.ordersInfoService.cancelOrdersByIdWithUserId(orderId, userId);
                        log.info("取消订单,订单id：{}，用户Id：{}", orderId, userId);
                        // 邮件通知对方。
                        this.userInfoService.sendNoticeMail(Collections.singletonList(userId),
                                "订单编号为" + orderId + "的订单超时未支付，请重新下单！");
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

            }
        }).start();
    }

    /**
     * 添加订单到延迟队列里面
     *
     * @param orderId   订单Id
     * @param delayTime 延迟时间，默认1
     * @param timeUnit  单位，默认天
     */
    public void offer(String orderId, Long delayTime, TimeUnit timeUnit) {

        //3 发送消息到延迟队列里面
        //设置过期时间
        delayedQueue.offer(orderId,
                Objects.isNull(delayTime) ? 1L : delayTime,
                Objects.isNull(timeUnit) ? TimeUnit.DAYS : timeUnit);
    }

    public void offer(String orderId) {
        offer(orderId, null, null);
    }


    /**
     * 删除订单
     *
     * @param orderId
     */
    public void remove(String orderId) {
        delayedQueue.remove(orderId);
    }
}
